package services

import (
	"dahuang/models"
	"fmt"
	"time"
)

var (
	//参数解析服务默认对象
	SystemParamServiceDefault = systemParamService{
		callParams: make(map[string]*SysCallParams),
	}

	//短语词库：短语，人类在交谈之中，语速中稍微的停顿将一句话分割成短语，这些短语被记录到大脑之中形成巨大的短语库
	//这里我们也模拟人类的短语库，
	//人类理解语句的时候，使用短语逐字匹配出多种可能的结果，并根据多组结果选取最“通顺”的结果，如果定义所谓的通顺是我们要解决的问题
	//每个短语可能带有情绪、联想：同义词，反义词？具体是什么，暂时待定，我们用interface占位
	phraseLibrary = map[string]interface{}{
		"两只":nil,
		"美丽的":nil,
		"画眉":nil,
		"高兴地":nil,
		"唱":nil,
		"一首":nil,
		"歌":nil,
		"今天":nil,
		"是":nil,
		"几号":nil,
		"了":nil,
	}
)

//参数解析服务
type systemParamService struct {
	callParams map[string]*SysCallParams
}

//系统调用参数
type SysCallParams struct {
	Params []interface{}
	LastDate time.Time
}

//获取位置上的参数
func (this *SysCallParams) GetParam(pos int) interface{} {
	if this.Params == nil {
		this.Params = make([]interface{}, 10)
	}
	if time.Now().Sub(this.LastDate) > time.Minute {
		return nil
	}
	le := len(this.Params)
	if pos >= le {
		return nil
	}
	return this.Params[pos]
}

func (this *SysCallParams) SetParam(pos int, val interface{}) {
	if this.Params == nil {
		this.Params = make([]interface{}, 10)
	}
	//参数内存不够了，追加10个
	if len(this.Params) <= pos {
		lessLen := pos + 10 - len(this.Params)
		tmp := make([]interface{}, lessLen)
		this.Params = append(this.Params, tmp...)
	}
	this.Params[pos] = val
	this.LastDate = time.Now()
}

//解析参数回调函数
type ParamResolveCallback func(*SysCallParams) error

//resolve 处理解析语句参数
//@return 解析成功的参数，成功识别参数数量， 错误
func (this *systemParamService) resolve(callFn string, callback ParamResolveCallback) (*SysCallParams, int, error) {
	//初始化全局参数
	cp := this.callParams[callFn]
	if cp == nil {
		cp = &SysCallParams{}
		this.callParams[callFn] = cp
	}

	//执行解析函数
	newCp := &SysCallParams{}
	err := callback(newCp)
	if err != nil {
		return nil, 0, err
	}

	//新旧比较
	oldLen := len(cp.Params)
	newLen := len(newCp.Params)
	fetchCnt := 0
	var result *SysCallParams
	if oldLen >= newLen {
		for i:=0; i<oldLen; i++ {
			tmp := newCp.GetParam(i)
			if tmp != nil {
				fetchCnt++
				cp.SetParam(i, tmp)
			}
		}
		result = cp
	} else {
		for i := 0; i< newLen ;i++ {
			newTmp := newCp.GetParam(i)
			if newTmp != nil {
				fetchCnt++
			} else {
				newCp.SetParam(i, cp.GetParam(i))
			}
		}
		result = newCp
	}
	//更新参数
	this.callParams[callFn] = result

	return result, fetchCnt, nil
}

//汉语词性
type WordCategorys struct {
	Word string

	//1.名词、2.动词、3.形容词、4.数词、5.量词、6.代词
	//7.副词、8.介词、9.连词、10.助词、11.拟声词、12.叹词
	Category int
}

type wordCategorySplit struct {
	lastId int

	words []WordCategorys
}

func (this wordCategorySplit) copy() wordCategorySplit {
	news := wordCategorySplit{
		lastId:this.lastId,
		words:make([]WordCategorys, 0),
	}
	for _,v := range this.words {
		news.words = append(news.words, v)
	}

	return news
}

//解析语句参数
//解析主谓宾，定状补，主定，宾定，
//介词，连词，量词
func (this *systemParamService) Parse(word string) {
	models.BuildActionIndex()
	models.BuildFuciIndex()
	models.BuildXingRongIndex()

	//使用词库逐词匹配，然后验证可能结果是否通顺
	wordRunes := []rune(word)
	lens := len(wordRunes)

	//期望的匹配
	expires := []*wordCategorySplit{
		&wordCategorySplit{
			lastId:0,
			words:make([]WordCategorys, 0),
		},
	}

	for i := 0; i< lens; i++ {
		for _,v := range expires {
			vLastId := v.lastId
			currentV := v.copy()
			//匹配形容词
			if newV := this.parseCategory(models.ActionXingRongIndex, v, wordRunes, i, vLastId, 3, currentV); len(newV) != 0 {
				expires = append(expires, newV...)
			}
			//匹配副词
			if newV := this.parseCategory(models.ActionFuciIndex, v, wordRunes, i, vLastId, 7, currentV); len(newV) != 0 {
				expires = append(expires, newV...)
			}
			//匹配动词
			if newV := this.parseCategory(models.ActionWordIndex, v, wordRunes, i, vLastId, 2, currentV); len(newV) != 0 {
				expires = append(expires, newV...)
			}
			//匹配量词
			//匹配介词
			//匹配连词
			//全部没有匹配上视为名词
			if v.lastId == vLastId && vLastId < i+1 {
				//前缀都无法匹配，则前进
				v.lastId = i+1
				v.words = append(v.words, WordCategorys{
					Word:     string(wordRunes[vLastId:i+1]),
					Category: 1,
				})
			}
		}
	}
	//未匹配的统一定义为名词
	fmt.Println("expires:-----------", len(expires))
	for _,v := range expires {
		fmt.Printf("%d,%+v\n", v.lastId, v.words)
	}
	//结合词性分析主谓宾，定状补，审核名词是否通顺
}

func (this *systemParamService) parseCategory(ciku map[string]map[string]string,v *wordCategorySplit, wordRunes []rune, i, vLastId, categoryId int, currentV wordCategorySplit) (newSplits []*wordCategorySplit) {
	if i < vLastId {
		return
	}
	prefix := string(wordRunes[vLastId:vLastId+1])
	newSplits = make([]*wordCategorySplit, 0)
	//匹配形容词
	if tmp := ciku[prefix]; tmp != nil {
		lens := len(wordRunes)
		for key,_ := range tmp {
			lenKey := len([]rune(key))
			if vLastId+lenKey > lens {
				continue
			}
			newLastId := vLastId+lenKey
			if string(wordRunes[vLastId:newLastId]) == key {
				if v.lastId == vLastId {
					v.lastId = newLastId
					v.words = append(v.words, WordCategorys{
						Word:     key,
						Category: categoryId,
					})
				} else {
					newV := currentV.copy()
					newV.lastId = newLastId
					newV.words = append(newV.words, WordCategorys{
						Word:     key,
						Category: categoryId,
					})
					newSplits = append(newSplits, &newV)
				}
			}
		}
	}

	return newSplits
}


func (this *systemParamService) ParseDingZhuanBu(word string) {

}